﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using Domain = DIT.Domain;
using Utility = DIT.Utility;
using Contract = DIT.Contract;
using Model = DIT.Client.Common.Model;
using Common = DIT.Client.Common;

namespace DIT.Client.MVVM.ViewModel
{
    public class ClientWorkspaceViewModel : Common.INotifier
    {
        private Contract.ITaxPayerService TaxPayerService { get { return ServiceHelper.TaxPayerServiceHelper.Instance.Service; } }
        private IEnumerable<Domain.Account> initialAccountList;
        private ObservableCollection<Model.AccountModel> workingClientVMList;
        private List<Model.AccountModel> SelectedClientList { get { return workingClientVMList.Where(cvm => { return cvm.IsSelected; }).ToList<Model.AccountModel>(); } }

        public ClientWorkspaceViewModel()
        {
            Init();
        }

        private void Init()
        {
            RefreshClientList();

            SaveCommand = new ModelCommand(new Action<object>(this.OnSave));
            //SaveCommand = new ModelCommand(new Action<object>(this.OnSave), new Func<object, bool>(this.CanSave));
            UndoCommand = new ModelCommand(new Action<object>(this.OnUndo));
            //UndoCommand = new ModelCommand(new Action<object>(this.OnUndo), new Func<object, bool>(this.CanUndo));
            DeleteCommand = new ModelCommand(new Action<object>(this.OnDelete));
            RefreshCommand = new ModelCommand(new Action<object>(this.OnRefresh));
            NewCommand = new ModelCommand(new Action<object>(this.OnNew));
        }

        public IEnumerable<Model.AccountModel> ClientCollection { get { return workingClientVMList; } }
        public bool DoesNotContainNewClient
        {
            get
            {
                return ClientCollection.FirstOrDefault(cvm => { return cvm.IsNew; }) == null;
            }
        }
        private string infoMessage = null;
        public string InfoMessage { get { return infoMessage; } set { infoMessage = value; RaisePropertyChangedEvent("InfoMessage"); } }
        private string actionMessage = null;
        public string ActionMessage { get { return actionMessage; } set { actionMessage = value; RaisePropertyChangedEvent("ActionMessage"); } }
        private string filterText;
        public string FilterText
        {
            get { return filterText;}
            set
            {
                filterText = value;
                RaisePropertyChangedEvent("FilterText");
                RaisePropertyChangedEvent("ClientCollection");
            }
        }

        public Model.AccountModel SelectedClient { get; set; }

        public ModelCommand SaveCommand { get; private set; }
        public ModelCommand DeleteCommand { get; private set; }
        public ModelCommand UndoCommand { get; private set; }
        public ModelCommand RefreshCommand { get; private set; }
        public ModelCommand NewCommand { get; private set; }

        private void OnSave(object parameter)
        {
            if (SelectedClient != null)
            {
                if (SelectedClient.IsValid)
                {
                    if (SelectedClient.ID == Guid.Empty)
                    {
                        Guid newid = Guid.Empty;
                        SelectedClient.Update();
                        try
                        {
                            newid = TaxPayerService.CreateTaxPayer(SelectedClient.AccountEntity);
                        }
                        catch
                        {
                            ActionMessage = string.Format(Utility.DITConfig.AppSettings["ClientCreationFailed"], SelectedClient.DisplayName);
                            return;
                        }

                        if (newid != Guid.Empty)
                            ActionMessage = string.Format(Utility.DITConfig.AppSettings["ClientCreationSuccess"], SelectedClient.DisplayName);
                        else
                            ActionMessage = string.Format(Utility.DITConfig.AppSettings["ClientCreationFailed"], SelectedClient.DisplayName);
                        RefreshClientList();
                    }
                    else if (SelectedClient.IsDirty)
                    {
                        bool success = false;
                        //DIT.Business.Domain.Client modifiedClient = initialClientList.First<DIT.Business.Domain.Client>(c => { return c.ID == SelectedClient.ID; });
                        //SelectedClient.CopyTo(modifiedClient);
                        SelectedClient.Update();
                        try
                        {
                            success = TaxPayerService.ModifyTaxPayer(SelectedClient.AccountEntity);
                        }
                        catch
                        {
                            ActionMessage = string.Format(Utility.DITConfig.AppSettings["ClientModificationFailed"], SelectedClient.DisplayName);
                            return;
                        }

                        if (success)
                            ActionMessage = string.Format(Utility.DITConfig.AppSettings["ClientModificationSuccess"], SelectedClient.DisplayName);
                        else
                            ActionMessage = string.Format(Utility.DITConfig.AppSettings["ClientModificationFailed"], SelectedClient.DisplayName);
                        RefreshClientList();
                    }
                    else
                        ActionMessage = Utility.DITConfig.AppSettings["NoChanges"];
                }
                else
                    ActionMessage = SelectedClient.Error;
            }
            else
                ActionMessage = Utility.DITConfig.AppSettings["NoClientSelected"];

        }
        private void OnUndo(object parameter)
        {
            if (SelectedClient != null && SelectedClient.IsDirty)
                SelectedClient.Refresh();
            else
                ActionMessage = SelectedClient == null ? Utility.DITConfig.AppSettings["NoClientSelected"]
                    : !SelectedClient.IsDirty ? Utility.DITConfig.AppSettings["NoChanges"]
                    : Utility.DITConfig.AppSettings["UndoNotWorking"];
        }
        private void OnRefresh(object parameter)
        {
            RefreshClientList();
        }
        private void OnDelete(object parameter)
        {
            if (SelectedClient != null)
            {
                if(SelectedClient.IsNew)
                {
                    workingClientVMList.Remove(SelectedClient);
                    RaisePropertyChangedEvent("DoesNotContainNewClient");
                    if(workingClientVMList != null && workingClientVMList.Count > 0)
                        workingClientVMList[0].IsSelected = true;
                }
                else
                {
                    StringBuilder deleteFailMessage = null;
                    SelectedClientList.ForEach(sc =>
                    {
                        try
                        {
                            //Delete from database
                            TaxPayerService.DeleteTaxPayer(sc.ID);
                            //workingClientVMList.Remove(sc);
                        }
                        catch
                        {
                            deleteFailMessage = deleteFailMessage ?? new StringBuilder("Delete failed for ");
                            deleteFailMessage.Append(sc.DisplayName + ", ");
                        }
                    });

                    if (deleteFailMessage != null)
                        ActionMessage = deleteFailMessage.ToString().Trim().TrimEnd(',');
                    else
                        ActionMessage = string.Format("Deletion Success. {0} clients deleted.", SelectedClientList.Count);

                    RefreshClientList();
                }
            }
            else
                ActionMessage = string.Format("No client selected for Deletion.");
        }
        private void OnNew(object parameter)
        {
            //Deselect all item of workingClientVMList
            if (workingClientVMList != null && workingClientVMList.Count > 0)
            {
                var v = workingClientVMList.Where(cvm => { return cvm.ID == Guid.Empty; });
                if (v != null && v.Count() > 0)
                {
                    ActionMessage = string.Format("Already a new client added in the list. Please work on that.");
                    return;
                }
                workingClientVMList.First(cvm => { return cvm.IsSelected == true; }).IsSelected = false;
            }
            else
                workingClientVMList = new ObservableCollection<Model.AccountModel>();
            //Create a New Default ViewModel
            Model.AccountModel newVM = new Model.AccountModel(Domain.IndividualAccount.Default);
            workingClientVMList.Insert(0, newVM);
            newVM.IsSelected = true;

            RaisePropertyChangedEvent("ClientCollection");
            RaisePropertyChangedEvent("DoesNotContainNewClient");
            ActionMessage = string.Format("Modify data for new client and save it.");
        }

        private void RefreshClientList()
        {
            Guid savePreviousClientId = Guid.Empty;
            if (SelectedClient != null)
                savePreviousClientId = SelectedClient.ID;

            if (initialAccountList != null && initialAccountList.Count() > 0)
                initialAccountList = initialAccountList.Except(initialAccountList);
            initialAccountList = TaxPayerService.GetAllClient();

            if (workingClientVMList != null && workingClientVMList.Count > 0)
                workingClientVMList.Clear();
            else
                workingClientVMList = new ObservableCollection<Model.AccountModel>();

            foreach (DIT.Domain.Account initialClient in initialAccountList)
            {
                workingClientVMList.Add(new Model.AccountModel(initialClient));
            }

            //Setting First Item or Recent Item as Selected
            if (workingClientVMList != null && workingClientVMList.Count > 0)
            {
                Model.AccountModel cvm = null;
                if(savePreviousClientId != Guid.Empty)
                    cvm = workingClientVMList.FirstOrDefault<Model.AccountModel>(c => { return c.ID == savePreviousClientId; });
                if (cvm == null)
                    workingClientVMList[0].IsSelected = true;
                else
                    cvm.IsSelected = true;
            }

            RaisePropertyChangedEvent("DoesNotContainNewClient");
            InfoMessage = string.Format(Utility.DITConfig.AppSettings["TotalClientCount"], workingClientVMList.Count);
        }
    }
}
